time: widen wallclock seconds to 64 bits
authorJan Beulich <jbeulich@suse.com>
Tue, 3 Feb 2015 10:25:47 +0000 (11:25 +0100)
committerJan Beulich <jbeulich@suse.com>
Tue, 3 Feb 2015 10:25:47 +0000 (11:25 +0100)
Linux is in the process of converting their seconds representation to
64 bits, so in order to support it consistently we should follow suit
(which at some point in quite a few years we'd have to do anyway). To
represent this in struct shared_info we leverage a 32-bit hole in
x86-64's and arm's variant of the structure; for x86-32 guests the only
(reasonable) choice we have is to put the extension in struct
arch_shared_info.

A note on the conditional suppressing the xen_wc_sec_hi helper macro
definition in the ix86 case for hypervisor and tools: Neither of the
two actually need this, and its presence causes the tools to fail to
build (due to the inclusion of both the x86-64 and x86-32 variants of
the header).

As a secondary change, x86's do_platform_op() gets a pointless
initializer as well as a pointless assignment of that same variable
dropped.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Tim Deegan <tim@xen.org>
Acked-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
15 files changed:
tools/include/xen-foreign/Makefile
tools/include/xen-foreign/reference.size
xen/arch/arm/time.c
xen/arch/x86/platform_hypercall.c
xen/arch/x86/time.c
xen/include/public/arch-arm.h
xen/include/public/arch-x86/xen-x86_32.h
xen/include/public/arch-x86/xen.h
xen/include/public/domctl.h
xen/include/public/platform.h
xen/include/public/xen.h
xen/include/xen/sched.h
xen/include/xen/time.h
xen/xsm/flask/hooks.c
xen/xsm/flask/policy/access_vectors

index ef8fc124a7569104ab78e4584b6d6824d5512c9d..80a446a5273b6b10276bb509a2c6e60c5f7d69d4 100644 (file)
@@ -17,7 +17,7 @@ clean:
 distclean: clean
 
 checker: checker.c $(headers)
-       $(HOSTCC) $(HOSTCFLAGS) -o $@ $<
+       $(HOSTCC) $(HOSTCFLAGS) -D__XEN_TOOLS__ -o $@ $<
 
 check-headers: checker
        ./checker > tmp.size
index ffe319e5560a6114a7f7aa020948d595ca3bd262..a0409db5c458aaede42bf2e649c8ebf599a27303 100644 (file)
@@ -9,6 +9,6 @@ vcpu_guest_context        |     344     344    2800    5168
 arch_vcpu_info            |       0       0      24      16
 vcpu_time_info            |      32      32      32      32
 vcpu_info                 |      48      48      64      64
-arch_shared_info          |       0       0      24      48
-shared_info               |    1088    1088    2340    3136
+arch_shared_info          |       0       0      28      48
+shared_info               |    1088    1088    2344    3136
 
index 37b85cd4aafa9702f083ba73260383d9e7e2537c..418748de7a32144ad12970f23b557230aac1a38b 100644 (file)
@@ -239,7 +239,7 @@ void update_vcpu_system_time(struct vcpu *v)
     /* XXX update shared_info->wc_* */
 }
 
-void domain_set_time_offset(struct domain *d, int32_t time_offset_seconds)
+void domain_set_time_offset(struct domain *d, int64_t time_offset_seconds)
 {
     d->time_offset_seconds = time_offset_seconds;
     /* XXX update guest visible wallclock time */
index a8dd43432940becdc6d4f7c09ef432ecb671487d..b427852c67ceeb774bd16fb8ab24397826f86e59 100644 (file)
@@ -187,7 +187,7 @@ static void resource_access(void *info)
 
 ret_t do_platform_op(XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op)
 {
-    ret_t ret = 0;
+    ret_t ret;
     struct xen_platform_op curop, *op = &curop;
 
     if ( copy_from_guest(op, u_xenpf_op, 1) )
@@ -212,14 +212,20 @@ ret_t do_platform_op(XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op)
 
     switch ( op->cmd )
     {
-    case XENPF_settime:
-    {
-        do_settime(op->u.settime.secs, 
-                   op->u.settime.nsecs, 
-                   op->u.settime.system_time);
-        ret = 0;
-    }
-    break;
+    case XENPF_settime32:
+        do_settime(op->u.settime32.secs,
+                   op->u.settime32.nsecs,
+                   op->u.settime32.system_time);
+        break;
+
+    case XENPF_settime64:
+        if ( likely(!op->u.settime64.mbz) )
+            do_settime(op->u.settime64.secs,
+                       op->u.settime64.nsecs,
+                       op->u.settime64.system_time);
+        else
+            ret = -EINVAL;
+        break;
 
     case XENPF_add_memtype:
     {
index 74c01e3710d8e4d4466df07465b9aab011e7dc17..5aca202320a8da8d642ebab13308db84e0077f1f 100644 (file)
@@ -47,7 +47,8 @@ string_param("clocksource", opt_clocksource);
 unsigned long __read_mostly cpu_khz;  /* CPU clock frequency in kHz. */
 DEFINE_SPINLOCK(rtc_lock);
 unsigned long pit0_ticks;
-static u32 wc_sec, wc_nsec; /* UTC time at last 'time update'. */
+static unsigned long wc_sec; /* UTC time at last 'time update'. */
+static unsigned int wc_nsec;
 static DEFINE_SPINLOCK(wc_lock);
 
 struct cpu_time {
@@ -902,6 +903,7 @@ void force_update_vcpu_system_time(struct vcpu *v)
 void update_domain_wallclock_time(struct domain *d)
 {
     uint32_t *wc_version;
+    unsigned long sec;
 
     spin_lock(&wc_lock);
 
@@ -909,8 +911,19 @@ void update_domain_wallclock_time(struct domain *d)
     *wc_version = version_update_begin(*wc_version);
     wmb();
 
-    shared_info(d, wc_sec)  = wc_sec + d->time_offset_seconds;
-    shared_info(d, wc_nsec) = wc_nsec;
+    sec = wc_sec + d->time_offset_seconds;
+    if ( likely(!has_32bit_shinfo(d)) )
+    {
+        d->shared_info->native.wc_sec    = sec;
+        d->shared_info->native.wc_nsec   = wc_nsec;
+        d->shared_info->native.wc_sec_hi = sec >> 32;
+    }
+    else
+    {
+        d->shared_info->compat.wc_sec         = sec;
+        d->shared_info->compat.wc_nsec        = wc_nsec;
+        d->shared_info->compat.arch.wc_sec_hi = sec >> 32;
+    }
 
     wmb();
     *wc_version = version_update_end(*wc_version);
@@ -931,7 +944,7 @@ static void update_domain_rtc(void)
     rcu_read_unlock(&domlist_read_lock);
 }
 
-void domain_set_time_offset(struct domain *d, int32_t time_offset_seconds)
+void domain_set_time_offset(struct domain *d, int64_t time_offset_seconds)
 {
     d->time_offset_seconds = time_offset_seconds;
     if ( is_hvm_domain(d) )
@@ -976,13 +989,13 @@ int cpu_frequency_change(u64 freq)
 }
 
 /* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
-void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base)
+void do_settime(unsigned long secs, unsigned int nsecs, u64 system_time_base)
 {
     u64 x;
     u32 y;
     struct domain *d;
 
-    x = SECONDS(secs) + (u64)nsecs - system_time_base;
+    x = SECONDS(secs) + nsecs - system_time_base;
     y = do_div(x, 1000000000);
 
     spin_lock(&wc_lock);
index 124fc90f2590db9d492c6f741aa7bee63c8ebed4..c2dcb66387f3007f2512b86762580a6ded13f038 100644 (file)
 
 #define XEN_HYPERCALL_TAG   0XEA1
 
+#define  int64_aligned_t  int64_t __attribute__((aligned(8)))
 #define uint64_aligned_t uint64_t __attribute__((aligned(8)))
 
 #ifndef __ASSEMBLY__
index 15041911edea9eb8a94a396a76d7eb43941695d2..be9a6c67da5a7a9fc7d62570b40de8251717450a 100644 (file)
     do { if ( sizeof(hnd) == 8 ) *(uint64_t *)&(hnd) = 0;   \
          (hnd).p = val;                                     \
     } while ( 0 )
+#define  int64_aligned_t  int64_t __attribute__((aligned(8)))
 #define uint64_aligned_t uint64_t __attribute__((aligned(8)))
 #define __XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name
 #define XEN_GUEST_HANDLE_64(name) __XEN_GUEST_HANDLE_64(name)
index c5e880b5ba49dcba2f5524e662f1a6ec2d40ce4e..232d4a5de21a6e15aad23ec6c2f27093d500756a 100644 (file)
@@ -255,6 +255,10 @@ struct arch_shared_info {
     unsigned long p2m_cr3;         /* cr3 value of the p2m address space */
     unsigned long p2m_vaddr;       /* virtual address of the p2m list */
     unsigned long p2m_generation;  /* generation count of p2m mapping */
+#ifdef __i386__
+    /* There's no room for this field in the generic structure. */
+    uint32_t wc_sec_hi;
+#endif
 };
 typedef struct arch_shared_info arch_shared_info_t;
 
index 57e2ed7460cee45c6f4d6ee4f5eb11fad0044c35..b3413a2b3479c9328f07750169d0a60665414546 100644 (file)
@@ -37,7 +37,7 @@
 #include "hvm/save.h"
 #include "memory.h"
 
-#define XEN_DOMCTL_INTERFACE_VERSION 0x0000000a
+#define XEN_DOMCTL_INTERFACE_VERSION 0x0000000b
 
 /*
  * NB. xen_domctl.domain is an IN/OUT parameter for this operation.
@@ -449,7 +449,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_hypercall_init_t);
 
 /* XEN_DOMCTL_settimeoffset */
 struct xen_domctl_settimeoffset {
-    int32_t  time_offset_seconds; /* applied to domain wallclock time */
+    int64_aligned_t time_offset_seconds; /* applied to domain wallclock time */
 };
 typedef struct xen_domctl_settimeoffset xen_domctl_settimeoffset_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t);
index 3e340b4148ab3248c0a4a8a174c996e8a11dc9b1..e4cf65f8976d5a84949ddb78e0d1e690162403c1 100644 (file)
  * Set clock such that it would read <secs,nsecs> after 00:00:00 UTC,
  * 1 January, 1970 if the current system time was <system_time>.
  */
-#define XENPF_settime             17
-struct xenpf_settime {
+#define XENPF_settime32           17
+struct xenpf_settime32 {
     /* IN variables. */
     uint32_t secs;
     uint32_t nsecs;
     uint64_t system_time;
 };
+#define XENPF_settime64           62
+struct xenpf_settime64 {
+    /* IN variables. */
+    uint64_t secs;
+    uint32_t nsecs;
+    uint32_t mbz;
+    uint64_t system_time;
+};
+#if __XEN_INTERFACE_VERSION__ < 0x00040600
+#define XENPF_settime XENPF_settime32
+#define xenpf_settime xenpf_settime32
+#else
+#define XENPF_settime XENPF_settime64
+#define xenpf_settime xenpf_settime64
+#endif
 typedef struct xenpf_settime xenpf_settime_t;
 DEFINE_XEN_GUEST_HANDLE(xenpf_settime_t);
 
@@ -579,6 +594,8 @@ struct xen_platform_op {
     uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
     union {
         struct xenpf_settime           settime;
+        struct xenpf_settime32         settime32;
+        struct xenpf_settime64         settime64;
         struct xenpf_add_memtype       add_memtype;
         struct xenpf_del_memtype       del_memtype;
         struct xenpf_read_memtype      read_memtype;
index a6a20926a5848be13c19d3746debda1cd978ac54..3703c3936e837fc3f53100e02bbb57b8a37ae4cc 100644 (file)
@@ -682,6 +682,12 @@ struct shared_info {
     uint32_t wc_version;      /* Version counter: see vcpu_time_info_t. */
     uint32_t wc_sec;          /* Secs  00:00:00 UTC, Jan 1, 1970.  */
     uint32_t wc_nsec;         /* Nsecs 00:00:00 UTC, Jan 1, 1970.  */
+#if !defined(__i386__)
+    uint32_t wc_sec_hi;
+# define xen_wc_sec_hi wc_sec_hi
+#elif !defined(__XEN__) && !defined(__XEN_TOOLS__)
+# define xen_wc_sec_hi arch.wc_sec_hi
+#endif
 
     struct arch_shared_info arch;
 
@@ -870,6 +876,9 @@ __DEFINE_XEN_GUEST_HANDLE(uint64, uint64_t);
 /* Default definitions for macros used by domctl/sysctl. */
 #if defined(__XEN__) || defined(__XEN_TOOLS__)
 
+#ifndef int64_aligned_t
+#define int64_aligned_t int64_t
+#endif
 #ifndef uint64_aligned_t
 #define uint64_aligned_t uint64_t
 #endif
index 814e08786c0ef4b084145c4c5247904e6ef68a5b..ccd7ed8d91a9cf41bed82a46ad46f57d36255f4d 100644 (file)
@@ -359,7 +359,7 @@ struct domain
     /* Domain is paused by controller software? */
     int              controller_pause_count;
 
-    int32_t          time_offset_seconds;
+    int64_t          time_offset_seconds;
 
 #ifdef HAS_PASSTHROUGH
     /* Does this guest need iommu mappings (-1 meaning "being set up")? */
index bb6259d5185c8b4a7f898a86e126167bf7903d96..bb19511bff676a71d6bcd6d511884370a553e21d 100644 (file)
@@ -65,11 +65,11 @@ extern void update_vcpu_system_time(struct vcpu *v);
 extern void update_domain_wallclock_time(struct domain *d);
 
 extern void do_settime(
-    unsigned long secs, unsigned long nsecs, u64 system_time_base);
+    unsigned long secs, unsigned int nsecs, u64 system_time_base);
 
 extern void send_timer_event(struct vcpu *v);
 
-void domain_set_time_offset(struct domain *d, int32_t time_offset_seconds);
+void domain_set_time_offset(struct domain *d, int64_t time_offset_seconds);
 
 #include <asm/time.h>
 
index d48463ffb8e47ce79cbb48d4f327f04f8443190f..65094bbe773fd8b218e28b949e2d44ff0aa0205c 100644 (file)
@@ -1365,7 +1365,8 @@ static int flask_platform_op(uint32_t op)
         return 0;
 #endif
 
-    case XENPF_settime:
+    case XENPF_settime32:
+    case XENPF_settime64:
         return domain_has_xen(current->domain, XEN__SETTIME);
 
     case XENPF_add_memtype:
index 1da9f63682d9c1c4c3946de0cec361c02b861c16..8f44b9d23a01372bb1817d47a3d535928ebb5c6d 100644 (file)
@@ -8,7 +8,8 @@
 # executing the hypercall, and the target is the xen initial sid (type xen_t).
 class xen
 {
-# XENPF_settime
+# XENPF_settime32
+# XENPF_settime64
     settime
 # XEN_SYSCTL_tbuf_op
     tbufcontrol